﻿<!---
 
  Copyright (c) 2010, Cristian Costantini - cristian@millemultimedia.it
  
  FileManager is licensed under the terms of the Open Source GPL 3.0 license. 
	
	http://www.gnu.org/licenses/gpl.html
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
--->
<cfcomponent output="false" extends="fileManager.util.AbsService" >

	<!--- Absolute File path of plugins installation database --->
	<cfset variables.jsonFile = expandPath( "/fileManager/config/Plugin.json" ) />
	
	<cffunction name="existsPluginConfig" access="private" returntype="boolean">
		<cfargument name="source" type="string" required="true" hint="Absolute file path."/>
		<cfset var result = "" />		
		
		<cflock name="#arguments.source#" type="readonly" timeout="30" throwontimeout="true" >
			
			<cfzip action="list"  name="result"
								  file="#arguments.source#" 
								  recurse="true">
					
					<cfzipparam filter="Plugin.xml" />			  
			
			</cfzip>

		</cflock>
		
		<cfreturn result.recordCount eq 1 />
	</cffunction>
	
	<cffunction name="pluginAlreadyInstalled" access="private" returntype="boolean">
		<cfargument name="source" type="string" required="true" hint="Absolute file path."/>
		<cfset var result = false />		
		<cfset var json = "" />
		<cfset var iterator = "" />
		<cfset var next = "" />
		<cfset var myXml = "" />
		
		<cflock name="#arguments.source#" type="readonly" timeout="30" throwontimeout="true" >
			
			<cfzip action="read"  variable="myXml"
								  file="#arguments.source#" 
								  entryPath="#listFirst( getFileFromPath( arguments.source ), "." )#/Plugin.xml" />
		
		</cflock>
		
		<cflock name="#variables.jsonFile#" type="readonly" timeout="30" throwontimeout="true" >
			
			<cfset json = deserializeJSON( readFile( variables.jsonFile ) ) />
		
		</cflock>
		
		<cfset myXml = xmlParse( myXml ) />
		
		<cfset iterator = json.plugins.iterator() />
		
		<cfloop condition="#iterator.hasNext()#">
		
			<cfset next = iterator.next() />
		
			<cfif next.id eq  myXml.plugin.XmlAttributes.id and next.version eq myXml.plugin.XmlAttributes.version >
				<cfset result = true/>
				<cfbreak/>
			</cfif>
			
		</cfloop>

		
		<cfreturn result/>
	</cffunction>

	<cffunction name="installPlugin" access="public" returntype="Struct" >
		<cfargument name="source" type="string" required="true" hint="Absolute file path."/>
		<cfset var result = structNew() />
		<cfset var json = arrayNew(1) />
		<cfset var fileName =  variables.jsonFile />
		<cfset var myXml = "" />
		<cfset var plugin = structNew()  />
		<cfset var iterator = "" />
		<cfset var next = "" />
		
		<cfset arguments.source = getAbsolutePath( arguments.source ) />
		
		<cftry>
		
			<cfset validatePermission( "installPlugin" ) />
		
			<cfif listLast( arguments.source, '.' ) neq 'zip'>
				<cfthrow message="File type not supported." detail="File type not supported." />
			</cfif>
			
			
			<cfif not existsPluginConfig( arguments.source ) >
				<cfthrow message="Missing File Plugin.xml." detail="Missing File Plugin.xml." />			
			</cfif>
			
			
			<cfif pluginAlreadyInstalled( arguments.source ) >
				<cfthrow message="Plugin already installed on FileManager." detail="Plugin already installed on FileManager." />			
			</cfif>
			
			<cflock name="#arguments.source#" type="readonly" timeout="30" throwontimeout="true" >
			
				<cfzip action="unzip" destination="#getAbsolutePath('/fileManager/plugin/')#" 
									  file="#arguments.source#" 
									  overwrite="true" />
			
			</cflock>
			
			<cfset myXml = xmlParse( readFile( expandPath( '/fileManager/plugin/#listFirst( getFileFromPath( arguments.source ), '.' )#/Plugin.xml') ) )/>
			
			<cflock name="#fileName#" type="readonly" timeout="30" throwontimeout="true" >
			
				<cfset json = deserializeJSON( readFile( fileName ) ) />
			
			</cflock>
			
			<!--- Check plugin installed. If plugin vesrion is the same update version. --->
			<cfset iterator = json.plugins.iterator() />
			
			<cfloop condition="#iterator.hasNext()#">
			
				<cfset next = iterator.next() />
			
				<cfif next.id eq  myXml.plugin.XmlAttributes.id and next.version neq myXml.plugin.XmlAttributes.version>
					
					<cfset json.plugins.remove( next ) />
					
					<cfbreak />
					
				</cfif>
			
			</cfloop>
			
			<cfset plugin['id'] = myXml.plugin.XmlAttributes.id />
			<cfset plugin['name'] = myXml.plugin.XmlAttributes.name />
			<cfset plugin['version'] = myXml.plugin.XmlAttributes.version />
			<cfset plugin['provider'] = myXml.plugin.XmlAttributes.provider />
			<cfset plugin['status'] = false />
			
			<cfset json.plugins.add( plugin ) />
			
			<cfset writeFile( fileName, serializeJSON( json ) ) />
			
			<cfset result['success'] = true />
			
			<cfcatch type="any">
				
				<cfset result['success'] = false />
                <cfset result['type'] = "it.millemultimedia.fileManager.plugins.PluginManager" />
                <cfset result['detail'] = cfcatch.detail />
                <cfset result['message'] = cfcatch.message />
            	
				<cfset variables.eventManager.notifyOnError( error = result ) />
				
			</cfcatch>
		
		</cftry>
		
		<cfreturn result/>
	</cffunction>
	
	<cffunction name="uninstallPlugin" access="public" returntype="Struct" >
		<cfargument name="name" type="string" required="true" />
		<cfset var result = structNew() />
		<cfset var json = arrayNew(1) />
		<cfset var fileName =  variables.jsonFile />
		<cfset var myXml = "" />
		<cfset var plugin = structNew()  />
		
		<cftry>
		
			<cfset validatePermission( "uninstallPlugin" ) />
			
			<cflock name="#fileName#" type="readonly" timeout="30" throwontimeout="true" >
			
				<cfset json = deserializeJSON( readFile( fileName ) ) />
			
			</cflock>
			
			<cfloop index="i" from="1" to="#arrayLen( json.plugins )#">
			
				<cfif json.plugins[i].name eq  arguments.name>
					<cfset plugin = json.plugins[i] />
				</cfif>
			
			</cfloop>
			
			<cfset json.plugins.remove( plugin ) />
			
			<cfdirectory action="delete" directory="#expandPath( '/fileManager/plugin/#arguments.name#')#" recurse="true"  />
			
			<cfset writeFile( fileName, serializeJSON( json ) ) />
			
			<cfset result['success'] = true />
			
			<cfcatch type="any">
				
				<cfset result['success'] = false />
                <cfset result['type'] = "it.millemultimedia.fileManager.plugins.PluginManager" />
                <cfset result['detail'] = cfcatch.detail />
                <cfset result['message'] = cfcatch.message />
            	
				<cfset variables.eventManager.notifyOnError( error = result ) />
				
			</cfcatch>
		
		</cftry>
		
		<cfreturn result/>
	</cffunction>
	
	<cffunction name="getPluginList" access="public" returntype="Struct" >
		<cfset var i = 0 />
		<cfset var json = arrayNew(1) />
		<cfset var fileName = variables.jsonFile />
		<cfset var result = structNew() />
		
		<cftry>
		
			<cfset validatePermission( "getPluginList" ) />
		
			<cflock name="#fileName#" type="readonly" timeout="30" throwontimeout="true" >
			
				<cfset json = deserializeJSON( readFile( fileName ) ) />
			
			</cflock>
			
			<cfset result['installed'] = arrayNew(1) />
			<cfset result['uninstalled'] = arrayNew(1) />
			
			<cfloop index="i" from="1" to="#arrayLen( json.plugins )#">
			
				<cfif json.plugins[i].status>
					<cfset result['installed'].add(  json.plugins[i] ) />
				<cfelse>
					<cfset result['uninstalled'].add( json.plugins[i] ) />
				</cfif>
			
			</cfloop>
			
			<cfset result['success'] = true />
			
			<cfcatch type="any">
				
				<cfset result['success'] = false />
                <cfset result['type'] = "it.millemultimedia.fileManager.plugins.PluginManager" />
                <cfset result['detail'] = cfcatch.detail />
                <cfset result['message'] = cfcatch.message />
            	
				<cfset variables.eventManager.notifyOnError( error = result ) />
				
			</cfcatch>
		
		</cftry>
		
		<cfreturn result/>
	</cffunction>
	
	<cffunction name="changeStatus" access="public" returntype="Struct" >
		<cfargument name="name" type="string" required="true" />
		<cfargument name="status" type="boolean" required="true" />
		<cfset var i = 0 />
		<cfset var json = arrayNew(1) />
		<cfset var fileName = variables.jsonFile />
		<cfset var result = structNew() />
		
		<cftry>
		
			<cfset validatePermission( "changeStatus" ) />
		
			<cflock name="#fileName#" type="readonly" timeout="30" throwontimeout="true" >
			
				<cfset json = deserializeJSON( readFile( fileName ) ) />
			
			</cflock>
			
			<cfloop index="i" from="1" to="#arrayLen( json.plugins )#">
			
				<cfif json.plugins[i].name eq  arguments.name>
					<cfset plugin = json.plugins[i] />
					<cfset plugin.status = arguments.status />
				</cfif>
			
			</cfloop>
			
			<cfset writeFile( fileName, serializeJSON( json ) ) />
			
			<cfset result['success'] = true />
			
			<cfcatch type="any">
				
				<cfset result['success'] = false />
                <cfset result['type'] = "it.millemultimedia.fileManager.plugins.PluginManager" />
                <cfset result['detail'] = cfcatch.detail />
                <cfset result['message'] = cfcatch.message />
            	
				<cfset variables.eventManager.notifyOnError( error = result ) />
				
			</cfcatch>
		
		</cftry>
		
		<cfreturn result/>
	</cffunction>

</cfcomponent>